home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH4 / SRC / REDUCEF.FRM (.txt) < prev    next >
Encoding:
Visual Basic Form  |  1997-01-03  |  14.4 KB  |  472 lines

  1. VERSION 4.00
  2. Begin VB.Form ReduceForm 
  3.    Caption         =   "Reduce"
  4.    ClientHeight    =   5205
  5.    ClientLeft      =   1110
  6.    ClientTop       =   1050
  7.    ClientWidth     =   6945
  8.    Height          =   5895
  9.    Left            =   1050
  10.    LinkTopic       =   "Form1"
  11.    ScaleHeight     =   347
  12.    ScaleMode       =   3  'Pixel
  13.    ScaleWidth      =   463
  14.    Top             =   420
  15.    Width           =   7065
  16.    Begin VB.PictureBox Pict 
  17.       AutoRedraw      =   -1  'True
  18.       Height          =   2310
  19.       Index           =   2
  20.       Left            =   4620
  21.       Picture         =   "REDUCEF.frx":0000
  22.       ScaleHeight     =   150
  23.       ScaleMode       =   3  'Pixel
  24.       ScaleWidth      =   150
  25.       TabIndex        =   2
  26.       Top             =   2880
  27.       Width           =   2310
  28.    End
  29.    Begin VB.PictureBox Pict 
  30.       AutoRedraw      =   -1  'True
  31.       Height          =   2310
  32.       Index           =   1
  33.       Left            =   4620
  34.       Picture         =   "REDUCEF.frx":0446
  35.       ScaleHeight     =   150
  36.       ScaleMode       =   3  'Pixel
  37.       ScaleWidth      =   150
  38.       TabIndex        =   1
  39.       Top             =   240
  40.       Width           =   2310
  41.    End
  42.    Begin VB.PictureBox Pict 
  43.       AutoRedraw      =   -1  'True
  44.       Height          =   4560
  45.       Index           =   0
  46.       Left            =   0
  47.       Picture         =   "REDUCEF.frx":088C
  48.       ScaleHeight     =   300
  49.       ScaleMode       =   3  'Pixel
  50.       ScaleWidth      =   300
  51.       TabIndex        =   0
  52.       Top             =   360
  53.       Width           =   4560
  54.    End
  55.    Begin MSComDlg.CommonDialog FileDialog 
  56.       Left            =   4080
  57.       Top             =   4680
  58.       _Version        =   65536
  59.       _ExtentX        =   847
  60.       _ExtentY        =   847
  61.       _StockProps     =   0
  62.       CancelError     =   -1  'True
  63.    End
  64.    Begin VB.Label Label1 
  65.       Alignment       =   2  'Center
  66.       Caption         =   "ShrinkPicture Subroutine"
  67.       Height          =   255
  68.       Index           =   2
  69.       Left            =   4620
  70.       TabIndex        =   5
  71.       Top             =   2640
  72.       Width           =   2310
  73.    End
  74.    Begin VB.Label Label1 
  75.       Alignment       =   2  'Center
  76.       Caption         =   "PaintPicture Method"
  77.       Height          =   255
  78.       Index           =   1
  79.       Left            =   4620
  80.       TabIndex        =   4
  81.       Top             =   0
  82.       Width           =   2310
  83.    End
  84.    Begin VB.Label Label1 
  85.       Alignment       =   2  'Center
  86.       Caption         =   "Original Image"
  87.       Height          =   255
  88.       Index           =   0
  89.       Left            =   0
  90.       TabIndex        =   3
  91.       Top             =   120
  92.       Width           =   4500
  93.    End
  94.    Begin VB.Menu mnuFile 
  95.       Caption         =   "&File"
  96.       Begin VB.Menu mnuFileLoad 
  97.          Caption         =   "&Load..."
  98.          Shortcut        =   ^L
  99.       End
  100.       Begin VB.Menu mnuFileSep 
  101.          Caption         =   "-"
  102.       End
  103.       Begin VB.Menu mnuFileExit 
  104.          Caption         =   "E&xit"
  105.       End
  106.    End
  107.    Begin VB.Menu mnuScaleMnu 
  108.       Caption         =   "&Scale"
  109.       Enabled         =   0   'False
  110.       Begin VB.Menu mnuScale 
  111.          Caption         =   "1/&2x"
  112.          Checked         =   -1  'True
  113.          Index           =   2
  114.       End
  115.       Begin VB.Menu mnuScale 
  116.          Caption         =   "1/&3x"
  117.          Index           =   3
  118.       End
  119.       Begin VB.Menu mnuScale 
  120.          Caption         =   "1/&4x"
  121.          Index           =   4
  122.       End
  123.       Begin VB.Menu mnuScale 
  124.          Caption         =   "1/&8x"
  125.          Index           =   8
  126.       End
  127.    End
  128. Attribute VB_Name = "ReduceForm"
  129. Attribute VB_Creatable = False
  130. Attribute VB_Exposed = False
  131. Option Explicit
  132. Dim SysPalSize As Integer
  133. Dim NumStaticColors As Integer
  134. Dim StaticColor1 As Integer
  135. Dim StaticColor2 As Integer
  136. Dim LogPal As Integer
  137. Dim palentry(0 To 255) As PALETTEENTRY
  138. Dim wid As Long
  139. Dim hgt As Long
  140. Dim bytes() As Byte
  141. Dim ScaleFactor As Integer
  142. ' ************************************************
  143. ' Draw the reduced images at the proper scale.
  144. ' ************************************************
  145. Sub DrawImages()
  146. Dim wid As Single
  147. Dim hgt As Single
  148. Dim x0 As Single
  149. Dim y0 As Single
  150. Dim i As Integer
  151.     WaitStart
  152.     ' Reduce using PaintPicture.
  153.     wid = Pict(0).ScaleWidth / ScaleFactor
  154.     hgt = Pict(0).ScaleHeight / ScaleFactor
  155.     x0 = (Pict(1).ScaleWidth - wid) / 2
  156.     y0 = (Pict(1).ScaleHeight - hgt) / 2
  157.     Pict(1).Cls
  158.     Pict(1).PaintPicture Pict(0).Image, _
  159.         x0, y0, wid, hgt
  160.     DoEvents
  161.     ' Reduce using ShrinkPicture.
  162.     wid = Pict(0).ScaleWidth / ScaleFactor
  163.     hgt = Pict(0).ScaleHeight / ScaleFactor
  164.     x0 = (Pict(2).ScaleWidth - wid) / 2
  165.     y0 = (Pict(2).ScaleHeight - hgt) / 2
  166.     Pict(2).Cls
  167.     ShrinkPicture Pict(0), Pict(2), _
  168.         0, 0, _
  169.         Pict(0).ScaleWidth - 1, Pict(0).ScaleHeight - 1, _
  170.         x0, y0, x0 + wid - 1, y0 + hgt - 1
  171.     DoEvents
  172.     ' Let each image repair its palette if needed.
  173.     For i = 0 To 2
  174.         Pict(i).ZOrder
  175.         DoEvents
  176.     Next i
  177.     WaitEnd
  178. End Sub
  179. ' ************************************************
  180. ' Shrink the picture in from_pic and place it
  181. ' in to_pic.
  182. ' ************************************************
  183. Sub ShrinkPicture( _
  184.     ByVal from_pic As Control, ByVal to_pic As Control, _
  185.     ByVal fx1 As Integer, ByVal fy1 As Integer, _
  186.     ByVal fx2 As Integer, ByVal fy2 As Integer, _
  187.     ByVal tx1 As Integer, ByVal ty1 As Integer, _
  188.     ByVal tx2 As Integer, ByVal ty2 As Integer)
  189. Dim bm As BITMAP
  190. Dim hbm As Integer
  191. Dim status As Long
  192. Dim from_bytes() As Byte
  193. Dim to_bytes() As Byte
  194. Dim from_wid As Long
  195. Dim from_hgt As Long
  196. Dim to_wid As Long
  197. Dim to_hgt As Long
  198. Dim xscale As Single
  199. Dim yscale As Single
  200. Dim tx As Integer
  201. Dim ty As Integer
  202. Dim x1 As Integer
  203. Dim y1 As Integer
  204. Dim x2 As Integer
  205. Dim y2 As Integer
  206. Dim X As Integer
  207. Dim Y As Integer
  208. Dim clr As Integer
  209.     ' Compute the scaling parameters.
  210.     xscale = (tx2 - tx1) / (fx2 - fx1)
  211.     yscale = (ty2 - ty1) / (fy2 - fy1)
  212.     ' Get from_pic's pixels.
  213.     hbm = from_pic.Image
  214.     status = GetObject(hbm, BITMAP_SIZE, bm)
  215.     from_wid = bm.bmWidthBytes
  216.     from_hgt = bm.bmHeight
  217.     ReDim from_bytes(0 To from_wid - 1, 0 To from_hgt - 1)
  218.     status = GetBitmapBits(hbm, from_wid * from_hgt, from_bytes(0, 0))
  219.     ' Get to_pic's pixels.
  220.     hbm = to_pic.Image
  221.     status = GetObject(hbm, BITMAP_SIZE, bm)
  222.     to_wid = bm.bmWidthBytes
  223.     to_hgt = bm.bmHeight
  224.     ReDim to_bytes(0 To to_wid - 1, 0 To to_hgt - 1)
  225.     status = GetBitmapBits(hbm, to_wid * to_hgt, to_bytes(0, 0))
  226.         
  227.     ' Skrink the image.
  228.     For ty = ty1 To ty2 - 1
  229.         y1 = Int((ty - ty1) / yscale + fy1)
  230.         y2 = Int((ty + 1 - ty1) / yscale + fy1) - 1
  231.         For tx = tx1 To tx2 - 1
  232.             x1 = Int((tx - tx1) / xscale + fx1)
  233.             x2 = Int((tx + 1 - tx1) / xscale + fx1) - 1
  234.             ' Average the values within the
  235.             ' from_pic box (x1, y1) - (x2, y2).
  236.             clr = 0
  237.             For Y = y1 To y2
  238.                 For X = x1 To x2
  239.                     clr = clr + palentry(from_bytes(X, Y)).peRed
  240.                 Next X
  241.             Next Y
  242.             clr = clr / (x2 - x1 + 1) / (y2 - y1 + 1)
  243.             to_bytes(tx, ty) = NearestNonstaticGray(clr)
  244.         Next tx
  245.     Next ty
  246.     ' Update from_pic.
  247.     status = SetBitmapBits(hbm, to_wid * to_hgt, to_bytes(0, 0))
  248.     to_pic.Refresh
  249. End Sub
  250. ' ***********************************************
  251. ' Load the control's palette so the non-static
  252. ' colors are grays. Map the logical palette to
  253. ' match the system palette. Convert the image to
  254. ' use the non-static grays.
  255. ' Set the following module global variables.
  256. '   LogPal      Image logical palette handle.
  257. '   palentry()  Image logical palette entries.
  258. '   wid         Width of image.
  259. '   hgt         Height of image.
  260. '   bytes(1 To wid, 1 To hgt)
  261. '               Image pixel values.
  262. ' ***********************************************
  263. Sub MatchGrayPalette(pic As Control)
  264. Dim sys(0 To 255) As PALETTEENTRY
  265. Dim i As Integer
  266. Dim bm As BITMAP
  267. Dim hbm As Integer
  268. Dim status As Long
  269. Dim X As Integer
  270. Dim Y As Integer
  271. Dim gray As Single
  272. Dim dgray As Single
  273. Dim c As Integer
  274. Dim clr As Integer
  275.     ' Make sure pic has the foreground palette.
  276.     pic.ZOrder
  277.     i = RealizePalette(pic.hdc)
  278.     DoEvents
  279.     ' Get the system palette entries.
  280.     i = GetSystemPaletteEntries(pic.hdc, 0, SysPalSize, sys(0))
  281.         
  282.     ' Get the image pixels.
  283.     hbm = pic.Image
  284.     status = GetObject(hbm, BITMAP_SIZE, bm)
  285.     wid = bm.bmWidthBytes
  286.     hgt = bm.bmHeight
  287.     ReDim bytes(1 To wid, 1 To hgt)
  288.     status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  289.     ' Make the logical palette as big as possible.
  290.     LogPal = pic.Picture.hPal
  291.     If ResizePalette(LogPal, SysPalSize) = 0 Then
  292.         Beep
  293.         MsgBox "Error resizing logical palette.", _
  294.             vbExclamation
  295.         Exit Sub
  296.     End If
  297.     ' Blank the non-static colors.
  298.     For i = 0 To StaticColor1
  299.         palentry(i) = sys(i)
  300.     Next i
  301.     For i = StaticColor1 + 1 To StaticColor2 - 1
  302.         With palentry(i)
  303.             .peRed = 0
  304.             .peGreen = 0
  305.             .peBlue = 0
  306.             .peFlags = PC_NOCOLLAPSE
  307.         End With
  308.     Next i
  309.     For i = StaticColor2 To 255
  310.         palentry(i) = sys(i)
  311.     Next i
  312.     i = SetPaletteEntries(LogPal, 0, SysPalSize, palentry(0))
  313.     ' Insert the non-static grays.
  314.     gray = 0
  315.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  316.     For i = StaticColor1 + 1 To StaticColor2 - 1
  317.         c = gray
  318.         gray = gray + dgray
  319.         With palentry(i)
  320.             .peRed = c
  321.             .peGreen = c
  322.             .peBlue = c
  323.         End With
  324.     Next i
  325.     i = SetPaletteEntries(LogPal, StaticColor1 + 1, StaticColor2 - StaticColor1 - 1, palentry(StaticColor1 + 1))
  326.     ' Recreate the image using the new colors.
  327.     For Y = 1 To hgt
  328.         For X = 1 To wid
  329.             clr = bytes(X, Y)
  330.             With sys(clr)
  331.                 c = (CInt(.peRed) + .peGreen + .peBlue) / 3
  332.             End With
  333.             bytes(X, Y) = NearestNonstaticGray(c)
  334.         Next X
  335.     Next Y
  336.     status = SetBitmapBits(hbm, wid * hgt, bytes(1, 1))
  337.     ' Realize the gray palette.
  338.     i = RealizePalette(pic.hdc)
  339.     pic.Refresh
  340. End Sub
  341. ' ************************************************
  342. ' Return the index of the nonstatic gray closest
  343. ' to the given value (assuming the non-static
  344. ' colors are a gray scale created by
  345. ' MatchGrayPalette).
  346. ' ************************************************
  347. Function NearestNonstaticGray(c As Integer) As Integer
  348. Dim dgray As Single
  349.     If c < 0 Then
  350.         c = 0
  351.     ElseIf c > 255 Then
  352.         c = 255
  353.     End If
  354.     dgray = 255 / (StaticColor2 - StaticColor1 - 2)
  355.     NearestNonstaticGray = c / dgray + StaticColor1 + 1
  356. End Function
  357. Private Sub Form_Load()
  358. Dim i As Integer
  359.     ' Make sure the screen supports palettes.
  360.     If Not GetDeviceCaps(hdc, RASTERCAPS) And RC_PALETTE Then
  361.         Beep
  362.         MsgBox "This monitor does not support palettes.", _
  363.             vbCritical
  364.         End
  365.     End If
  366.     ' Get system palette size and # static colors.
  367.     SysPalSize = GetDeviceCaps(hdc, SIZEPALETTE)
  368.     NumStaticColors = GetDeviceCaps(hdc, NUMRESERVED)
  369.     StaticColor1 = NumStaticColors \ 2 - 1
  370.     StaticColor2 = SysPalSize - NumStaticColors \ 2
  371.     ' Make the pictures all use gray palettes.
  372.     ScaleFactor = 2
  373.     Me.Show
  374.     DoEvents
  375.     WaitStart
  376.     For i = 1 To 2
  377.         MatchGrayPalette Pict(i)
  378.     Next i
  379.     DoEvents
  380.     ' Let each image repair its palette if needed.
  381.     For i = 0 To 2
  382.         Pict(i).ZOrder
  383.         DoEvents
  384.     Next i
  385.     WaitEnd
  386. End Sub
  387. ' ***********************************************
  388. ' Reset the cursors for the form and all the
  389. ' picture boxes.
  390. ' ***********************************************
  391. Sub WaitEnd()
  392. Dim i As Integer
  393.     MousePointer = vbDefault
  394.     For i = 0 To 2
  395.         Pict(i).MousePointer = vbDefault
  396.     Next i
  397. End Sub
  398. ' ***********************************************
  399. ' Give the form and all the picture boxes an
  400. ' hourglass cursor.
  401. ' ***********************************************
  402. Sub WaitStart()
  403. Dim i As Integer
  404.     MousePointer = vbHourglass
  405.     For i = 0 To 2
  406.         Pict(i).MousePointer = vbHourglass
  407.     Next i
  408.     DoEvents
  409. End Sub
  410. Private Sub Form_Unload(Cancel As Integer)
  411.     End
  412. End Sub
  413. Private Sub mnuFileExit_Click()
  414.     Unload Me
  415. End Sub
  416. ' ***********************************************
  417. ' Load a new image file.
  418. ' ***********************************************
  419. Private Sub mnuFileLoad_Click()
  420. Dim fname As String
  421.     ' Allow the user to pick a file.
  422.     On Error Resume Next
  423.     FileDialog.filename = "*.BMP;*.ICO;*.RLE;*.WMF;*.DIB"
  424.     FileDialog.Flags = cdlOFNFileMustExist + cdlOFNHideReadOnly
  425.     FileDialog.ShowOpen
  426.     If Err.Number = cdlCancel Then
  427.         Exit Sub
  428.     ElseIf Err.Number <> 0 Then
  429.         Beep
  430.         MsgBox "Error selecting file.", , vbExclamation
  431.         Exit Sub
  432.     End If
  433.     On Error GoTo 0
  434.     fname = Trim$(FileDialog.filename)
  435.     FileDialog.InitDir = Left$(fname, Len(fname) _
  436.         - Len(FileDialog.FileTitle) - 1)
  437.     ' Load the picture.
  438.     WaitStart
  439.     LoadFromPict fname
  440.     mnuScaleMnu.Enabled = True
  441.     mnuScale_Click 2
  442.     WaitEnd
  443. End Sub
  444. ' ***********************************************
  445. ' Load the indicated file and prepare to work
  446. ' with its palette.
  447. ' ***********************************************
  448. Sub LoadFromPict(fname As String)
  449. Dim status As Long
  450.     On Error GoTo LoadFileError
  451.     Pict(0).Picture = LoadPicture(fname)
  452.     On Error GoTo 0
  453.         
  454.     MatchGrayPalette Pict(0)
  455.     Caption = "Reduce [" & fname & "]"
  456.     Exit Sub
  457. LoadFileError:
  458.     Beep
  459.     MsgBox "Error loading file " & fname & "." & _
  460.         vbCrLf & Error$
  461.     Exit Sub
  462. End Sub
  463. ' ************************************************
  464. ' Redraw the images at the new scale.
  465. ' ************************************************
  466. Private Sub mnuScale_Click(Index As Integer)
  467.     mnuScale(ScaleFactor).Checked = False
  468.     ScaleFactor = Index
  469.     mnuScale(ScaleFactor).Checked = True
  470.     DrawImages
  471. End Sub
  472.